package com.sxc.study;

import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Create by sunxunchao on 2019/10/12
 */
public class PoolActivity extends AppCompatActivity {

    private static final String TAG = "PoolActivity";

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final long KEEP_ALIVE = 10L;

    private static final ThreadPoolExecutor pool = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAXIMUM_POOL_SIZE,
            KEEP_ALIVE,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.DiscardPolicy());


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pool);

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Task task = new Task("one", 100);
                Task task2 = new Task("two", 7);
                Log.d(TAG, "onClick: start one");
                Future<Boolean> future = pool.submit(task);
                Log.d(TAG, "onClick: start two");
                Future<Boolean> future2 = pool.submit(task2);
                try {
                    boolean result = future.get(5000, TimeUnit.MILLISECONDS);
                    if (result) {
                        Log.d(TAG, "one complete successfully");
                    }
                } catch (InterruptedException e) {
                    Log.d(TAG, "future在睡着时被打断");
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    Log.d(TAG, "future在尝试取得任务结果时出错");
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    Log.d(TAG, "one future时间超时");
                    future.cancel(true);
                    e.printStackTrace();
                }
                try {
                    boolean result2 = future2.get(5000, TimeUnit.MILLISECONDS);
                    if (result2) {
                        Log.d(TAG, "two complete successfully");
                    }
                } catch (InterruptedException e) {
                    Log.d(TAG, "future在睡着时被打断");
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    Log.d(TAG, "future在尝试取得任务结果时出错");
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    Log.d(TAG, "two future时间超时");
                    future2.cancel(true);
                    e.printStackTrace();
                }
            }
        });
    }

    class Task implements Callable<Boolean> {

        public String name;
        private int time;

        public Task(String s, int t) {
            name = s;
            time = t;
        }

        @Override
        public Boolean call() throws Exception {
            for (int i = 0; i < time; ++i) {
                Log.d(TAG, "task " + name + " round " + (i + 1));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Log.d(TAG, name + " is interrupted when calculating, will stop...");
                    return false; // 注意这里如果不return的话，线程还会继续执行，所以任务超时后在这里处理结果然后返回
                }
            }
            return true;
        }
    }


}
